package com.md.application.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.md.api.InternalApi;
import com.md.client.OpenApiClient;
import com.md.config.SystemConfig;
import com.md.domain.model.po.RoleApiPO;
import com.md.domain.model.po.RoleModulePO;
import com.md.domain.model.po.RolePO;
import com.md.domain.model.po.UsersPO;
import com.md.domain.repository.RoleApiRepository;
import com.md.domain.repository.RoleModuleRepository;
import com.md.domain.repository.RoleRepository;
import com.md.domain.service.AuthenticationDomainServices;
import com.md.domain.service.ConfigDomainServices;
import com.md.infrastructure.config.DefaultUserConfig;
import com.md.model.system.CommonResult;
import com.md.request.ApiRequest;
import com.md.request.GlobalConfigRequest;
import com.md.request.QueryModuleRequest;
import com.md.response.ApiResponse;
import com.md.response.AppInfoResponse;
import com.md.response.ModuleResponse;
import com.md.util.PinYinUtil;
import com.md.value.GlobalConfigTypeEnum;
import com.md.value.RoleApiTypeEnum;
import com.md.value.RoleModuleTypeEnum;
import com.md.value.RoleStatusEnum;
import com.md.value.SexEnum;
import com.md.value.UsersStatusEnum;
import com.md.value.constants.DefaultServerContext;
import com.md.value.server.ServerContext;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author 刘骄阳
 * 2024-12-15 1:46
 */
@Service
@RequiredArgsConstructor
public class InternalApplication implements InternalApi {
  private final AuthenticationDomainServices authenticationDomainServices;
  private final ConfigDomainServices configDomainServices;
  private final RoleModuleRepository roleModuleRepository;
  private final RoleApiRepository roleApiRepository;
  private final RoleRepository roleRepository;
  private final SystemConfig systemConfig;
  private final DefaultUserConfig defaultUserConfig;

  @Override
  public CommonResult<Void> init() {
    Long appInfoId = systemConfig.getAppInfoId();
    AppInfoResponse userCenterAppInfo = OpenApiClient.queryAppInfoById(appInfoId);
    ServerContext.put(DefaultServerContext.TENANT_ID, userCenterAppInfo.getTenantId());
    ServerContext.put(DefaultServerContext.BRAND_ID, userCenterAppInfo.getBrandId());
    // 初始化用户
    RolePO role = new RolePO();
    role.setName(defaultUserConfig.getRoleName());
    role.setFirstLabel(PinYinUtil.getPinYinHeadChar(defaultUserConfig.getRoleName()));
    role.setStatus(RoleStatusEnum.NORMAL.getCode());
    authenticationDomainServices.createRole(role);

    // 初始化角色
    UsersPO users = new UsersPO();
    users.setName(defaultUserConfig.getUserName());
    users.setFirstLabel(PinYinUtil.getPinYinHeadChar(defaultUserConfig.getUserName()));
    users.setPassword(defaultUserConfig.getPassword());
    users.setAccount(defaultUserConfig.getAccount());
    users.setAvatar("");
    users.setSex(SexEnum.OTHER.getCode());
    users.setPhone("");
    users.setStatus(UsersStatusEnum.ACTIVE.getCode());
    authenticationDomainServices.createUser(users, Lists.newArrayList(role.getId()));

    List<ModuleResponse> moduleResponses = OpenApiClient.queryModuleList(new QueryModuleRequest());
    List<RoleModulePO> roleModuleList = Lists.newArrayList();
    List<RoleApiPO> roleApiList = Lists.newArrayList();
    moduleResponses.forEach(moduleResponse -> {
      RoleModulePO roleModule = new RoleModulePO();
      roleModule.setRoleId(role.getId());
      roleModule.setModuleId(moduleResponse.getId());
      roleModule.setIsOwner(1);
      roleModuleList.add(roleModule);
      List<AppInfoResponse> appInfoResponses = OpenApiClient.queryAppInfoByModuleId(moduleResponse.getId());
      appInfoResponses.forEach(appInfoResponse -> {
        ApiRequest request = new ApiRequest();
        request.setAppInfoId(appInfoResponse.getId());
        List<ApiResponse> apiResponses = OpenApiClient.queryApiList(request);
        apiResponses.forEach(apiResponse -> {
          RoleApiPO roleApi = new RoleApiPO();
          roleApi.setRoleId(role.getId());
          roleApi.setApiId(apiResponse.getId());
          roleApiList.add(roleApi);
        });
      });
    });
    roleModuleRepository.insertBatch(roleModuleList);
    roleApiRepository.insertBatch(roleApiList);
    // 初始化权限
    // 初始化配置
    GlobalConfigTypeEnum[] values = GlobalConfigTypeEnum.values();
    int maxSize = values.length;
    for (int i = 0; i < maxSize; i++) {
      configDomainServices.saveConfig(values[i], null);
    }
    return CommonResult.success();
  }

  @Override
  public CommonResult<Void> appendRolePermission() {
    ServerContext.put(DefaultServerContext.USER_ID, 1L);
    RolePO superRole = roleRepository.queryRoleByName(defaultUserConfig.getRoleName());
    List<ModuleResponse> moduleResponses = OpenApiClient.queryModuleList(new QueryModuleRequest());
    List<Long> moduleIdList = Lists.newArrayList();
    Map<Long, List<Long>> moduleApiMap = Maps.newHashMap();
    moduleResponses.forEach(moduleResponse -> {
      List<Long> apiIdList = Lists.newArrayList();
      moduleIdList.add(moduleResponse.getId());
      List<AppInfoResponse> appInfoResponses = OpenApiClient.queryAppInfoByModuleId(moduleResponse.getId());
      appInfoResponses.forEach(appInfoResponse -> {
        ApiRequest request = new ApiRequest();
        request.setAppInfoId(appInfoResponse.getId());
        List<ApiResponse> apiResponses = OpenApiClient.queryApiList(request);
        apiResponses.forEach(apiResponse -> apiIdList.add(apiResponse.getId()));
      });
      moduleApiMap.put(moduleResponse.getId(), apiIdList);
    });
    authenticationDomainServices.linkRoleModule(superRole.getId(), moduleIdList, Lists.newArrayList(), 1,
      RoleModuleTypeEnum.NORMAL_INSERT);
    moduleApiMap.forEach((moduleId, apiIdList) ->
      authenticationDomainServices.linkRoleApi(superRole.getId(), apiIdList, Lists.newArrayList(),
        RoleApiTypeEnum.NORMAL_INSERT, moduleId));
    return CommonResult.success();
  }

  @Override
  public CommonResult<Void> appendConfig(final GlobalConfigRequest request) {
    configDomainServices.saveConfig(request.getType(), request.getValue());
    return CommonResult.success();
  }
}
